package com.inspur.edp.formserver.viewmodel.common;

import com.inspur.edp.bef.bizentity.GspBusinessEntity;
import com.inspur.edp.bef.bizentity.operation.BizOperation;
import com.inspur.edp.bef.bizentity.operation.Determination;
import com.inspur.edp.bef.component.detailcmpentity.vm.VMComponent;
import com.inspur.edp.bef.component.detailcmpentity.vm.VMMethodParameter;
import com.inspur.edp.cef.designtime.api.IGspCommonField;
import com.inspur.edp.cef.designtime.api.element.GspElementDataType;
import com.inspur.edp.cef.designtime.api.exceptions.CefException;
import com.inspur.edp.cef.designtime.api.operation.CommonDetermination;
import com.inspur.edp.cef.designtime.api.util.MetadataUtil;
import com.inspur.edp.cef.designtime.api.variable.CommonVariable;
import com.inspur.edp.formserver.viewmodel.GspViewModel;
import com.inspur.edp.formserver.viewmodel.action.MappedCdpAction;
import com.inspur.edp.formserver.viewmodel.action.ViewModelAction;
import com.inspur.edp.formserver.viewmodel.action.ViewModelActionType;
import com.inspur.edp.formserver.viewmodel.action.mappedcdp.MappedCdpActionParameter;
import com.inspur.edp.formserver.viewmodel.action.ViewModelActionInfo;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.entity.MetadataReference;
import io.iec.edp.caf.commons.exception.ExceptionLevel;

import java.util.Iterator;
import java.util.List;
import java.util.UUID;

public class ViewModelActionUtil {
    private static final String BEID="beId";
    private static final String PROCESSCATEGORY="processCategory";
    private static final String BIZCAtEGORY="bizCategory";
    private static final String BEFORESAVE_COMPONENTID="be7a44fd-9a73-4595-8f28-9137ecb399aa";
    private static final String VARDTM_COMPONENTID="0315970a-488c-4454-8e64-c13cb3210c8c";
    private static final String SUMMARY="summary";

    private static final String VOACTIONID="811993be-7e11-4e0f-92d6-81c7669d586f";
    private static final String VARDETERMINATIONID="e88fe87d-7855-40e2-b6bd-149618251d61";

    private static final String BEFORESAVE_DETERMINATION_ID="6b3f4f6a-26f2-4199-8159-e36435c63245";
    private static final String DELETE_DETERMINATION_ID="0e7d3731-049b-49b9-9e46-2046ef957843";

    public final static void addVoActions(GspViewModel vm,String beId,String processCategory,String bizCategory,String summary){
        addDataExtendInfo(vm,beId,processCategory,bizCategory,summary);
    }
    public final static void removeActions(GspViewModel vm, GspBusinessEntity be,boolean enableDraft){
        if(enableDraft)
            return;

        if(vm.getDataExtendInfo().getBeforeSaveActions()!=null && vm.getDataExtendInfo().getBeforeSaveActions().size()!=0){
            Iterator<ViewModelAction> iterators=vm.getDataExtendInfo().getBeforeSaveActions().iterator();
            while (iterators.hasNext()){
                MappedCdpAction mappedCdpAction= (MappedCdpAction) iterators.next();
                if(VOACTIONID.equals(mappedCdpAction.getID())){
                    iterators.remove();
                    break;
                }

            }
        }

        if(be.getMainObject().getDeterminations()!=null && be.getMainObject().getDeterminations().size()!=0){
            Iterator<BizOperation> iterators=be.getMainObject().getDeterminations().iterator();
            while (iterators.hasNext()){
                Determination mappedCdpAction= (Determination) iterators.next();
                if(BEFORESAVE_DETERMINATION_ID.equals(mappedCdpAction.getID())) {
                    iterators.remove();
                    break;
                }
            }
        }

        if(be.getMainObject().getDeterminations()!=null && be.getMainObject().getDeterminations().size()!=0){
            Iterator<BizOperation> iterators=be.getMainObject().getDeterminations().iterator();
            while (iterators.hasNext()){
                Determination mappedCdpAction= (Determination) iterators.next();
                if(DELETE_DETERMINATION_ID.equals(mappedCdpAction.getID())){
                    iterators.remove();
                    break;
                }
            }
        }
    }
    public static MappedCdpAction getMappedCdpAction(String componentID){
        MappedCdpAction action=new MappedCdpAction();
        action.setID(VOACTIONID);
        String code = "InitDraftVar";
        action.setCode(code);
        action.setType(ViewModelActionType.VMAction);
        action.setName(code);
        action.setComponentEntityId(componentID);
        action.setComponentName("DraftVarBeforeSave");
        return action;
    }

    /**
     *
     * @param vm
     * @param beId
     * @param processCategory
     * @param bizCategory
     * @param summary
     */
    public final static void addDataExtendInfo(GspViewModel vm,String beId,String processCategory,String bizCategory,String summary){
        boolean isExistedAction=isExistedVoAction(vm,VOACTIONID);
        //是否已经添加
        if(isExistedAction)
            return;
        MappedCdpAction action=getMappedCdpAction(BEFORESAVE_COMPONENTID);

        GspMetadata metadata = MetadataUtil.getCustomMetadata(BEFORESAVE_COMPONENTID);
        if(metadata==null){
            throw  new CefException(ViewModelErrorCodes.GSP_BFF_MODEL_0001,String.format("未获取到元数据id为%1$s的构件元数据，请确认该元数据是否已入库，当前元数据类型为：VMComponent。",BEFORESAVE_COMPONENTID),null
            , ExceptionLevel.Error,true);
        }
        VMComponent vmComponent = (VMComponent) metadata.getContent();
        VMMethodParameter beIdPar = null;
        VMMethodParameter processCategoryPar = null;
        VMMethodParameter bizCategoryPar = null;
        VMMethodParameter summaryPar = null;
        for (VMMethodParameter param : vmComponent.getVmMethod().getParams()) {
            if (param.getParamCode().equalsIgnoreCase(BEID)) {
                beIdPar = param;
            } else if (param.getParamCode().equalsIgnoreCase(PROCESSCATEGORY)) {
                processCategoryPar = param;
            } else if (param.getParamCode().equalsIgnoreCase(BIZCAtEGORY)) {
                bizCategoryPar = param;
            }else if(param.getParamCode().equalsIgnoreCase(SUMMARY)){
                summaryPar=param;
            }
        }
        MappedCdpActionParameter parBeId = getMappedCdpActionParameter(beIdPar,beId);
        action.getParameterCollection().add(parBeId);

        MappedCdpActionParameter parProcessCategory = getMappedCdpActionParameter(processCategoryPar,processCategory);
        action.getParameterCollection().add(parProcessCategory);

        MappedCdpActionParameter parBizCategory = getMappedCdpActionParameter(bizCategoryPar,bizCategory);
        action.getParameterCollection().add(parBizCategory);

        MappedCdpActionParameter parSummary = getMappedCdpActionParameter(summaryPar,summary);
        action.getParameterCollection().add(parSummary);
        vm.getDataExtendInfo().getBeforeSaveActions().add(action);
    }

    private final static boolean isExistedVoAction(GspViewModel vm,String actionId){
        boolean isExist=false;
        if(vm.getDataExtendInfo().getBeforeSaveActions()==null || vm.getDataExtendInfo().getBeforeSaveActions().size()==0)
            isExist=false;
        for(ViewModelAction action :vm.getDataExtendInfo().getBeforeSaveActions()){
            if(actionId.equals(action.getID())){
                isExist=true;
                break;
            }
        }
        return isExist;
    }
    public static  MappedCdpActionParameter getMappedCdpActionParameter(VMMethodParameter beIdPar,String value){
        MappedCdpActionParameter parameter = new MappedCdpActionParameter();
        parameter.setID(beIdPar.getID());
        parameter.setParamName(beIdPar.getParamName());
        parameter.setParamCode(beIdPar.getParamCode());
        parameter.setParameterType(VMParameterType.String);
        parameter.getActualValue().setHasValue(true);
        parameter.getActualValue().setEnable(true);
        parameter.getActualValue().setValue(value);
        return parameter;
    }
    private static  CommonVariable getCommonVariable(String varCode){
        CommonVariable variable = new CommonVariable();
        variable.setID(UUID.randomUUID().toString());
        variable.setCode(varCode);
        variable.setName(varCode);
        variable.setMDataType(GspElementDataType.String);
        variable.setLabelID(varCode);
        variable.setLength(36);
        variable.setEnableRtrim(true);
        return variable;
    }

    /**
     *
     * @param vm
     */
    public static void addVariables(GspViewModel vm){

        addVariable(vm,"bffTaskDraftBeId");
        addVariable(vm,"bffTaskDraftProcessCategory");
        addVariable(vm,"bffTaskDraftBizCategory");
        addVariable(vm,"bffTaskDraftSummary");

    }

    public static  void addVariable(GspViewModel vm,String varCode){
        boolean isExistedVar=isExistedVariable(vm,varCode);
        if (isExistedVar)
            return;
        CommonVariable var=getCommonVariable(varCode);
        vm.getVariables().getContainElements().addField(var);
    }
    private static boolean isExistedVariable(GspViewModel vm,String varCode){
        boolean isExistedVariable=false;
        if(vm.getVariables().getContainElements()==null || vm.getVariables().getContainElements().size()==0)
            isExistedVariable=false;
        for (IGspCommonField variable :vm.getVariables().getContainElements()){
            if(varCode.equals(variable.getCode())){
                isExistedVariable=true;
                break;
            }
        }
        return isExistedVariable;
    }
    public static CommonDetermination getCommonOperation(String code,String name,String componentName,String componentId){
        CommonDetermination determination=new CommonDetermination();
        determination.setID(VARDETERMINATIONID);
        determination.setCode(code);
        determination.setName(name);
        determination.setComponentName(componentName);
        determination.setComponentId(componentId);
        return  determination;
    }

    /**
     *
     * @param vm
     */
    public static void addVarDeterminations(GspViewModel vm){
        boolean isExistedVarDtm=isExistedVarDtm(vm,VARDETERMINATIONID);
        if (isExistedVarDtm)
            return;
        CommonDetermination determination=  getCommonOperation("DraftVariableDtm","DraftVariableDtm","DraftVarDeterminationAction",VARDTM_COMPONENTID);
        vm.getVariables().getDtmAfterModify().add(determination);

    }
    private static boolean isExistedVarDtm(GspViewModel vm,String actionId){
        boolean isExist=false;
        if(vm.getVariables().getDtmAfterModify()==null || vm.getVariables().getDtmAfterModify().size()==0)
            isExist=false;
        for(CommonDetermination action :vm.getVariables().getDtmAfterModify()){
            if(actionId.equals(action.getID())){
                isExist=true;
                break;
            }
        }
        return isExist;
    }

    public static ViewModelActionInfo getActionInfo(MappedCdpAction action, GspViewModel viewModel,GspMetadata metadata) {
        ViewModelActionInfo actionInfo=new ViewModelActionInfo();
        actionInfo.setViewModel(viewModel);
        actionInfo.setCode(action.getCode());
        actionInfo.setName(action.getName());
        actionInfo.setCompId(action.getComponentEntityId());
        actionInfo.setCompName(action.getComponentName());
        actionInfo.setSourceMeta(metadata);
        return actionInfo;
    }

    public static ViewModelActionInfo getActionInfo(CommonDetermination determination, GspViewModel viewModel,GspMetadata metadata) {
        ViewModelActionInfo actionInfo=new ViewModelActionInfo();
        actionInfo.setViewModel(viewModel);
        actionInfo.setCode(determination.getCode());
        actionInfo.setName(determination.getName());
        actionInfo.setCompId(determination.getComponentId());
        actionInfo.setCompName(determination.getComponentName());
        actionInfo.setSourceMeta(metadata);
        return actionInfo;
    }

    public static String getViewModelMessage(GspViewModel viewModel,GspMetadata sourceMeta) {
        StringBuilder builder=new StringBuilder();
        builder.append("编号为").append("\"").append(viewModel.getCode()).append("\"").
                append(",名称为").append("\"").append(viewModel.getName()).append("\"");
        if (sourceMeta==null || sourceMeta.getHeader()==null)
            return builder.toString();
        builder.append(",命名空间为").append("\"").append(sourceMeta.getHeader().getNameSpace()).append("\"").
                append("的视图对象元数据,");
        return builder.toString();
    }
    public static String getExceptionMessage(GspMetadata metadata,String  id,StringBuilder builder){
        if (metadata==null|| metadata.getRefs()==null || metadata.getRefs().size()==0){
            return builder.toString();
        }
        MetadataReference ref = getReference(metadata.getRefs(),id);
        if (ref==null || ref.getDependentMetadata()==null){
            return builder.toString();
        }
        builder.append(",编号为").append("\"").append(ref.getDependentMetadata().getCode()).append("\"").
                append(",名称为").append("\"").append(ref.getDependentMetadata().getName()).append("\"").
                append(",命名空间为").append("\"").append(ref.getDependentMetadata().getNameSpace()).append("\"");
        return builder.toString();
    }

    private static MetadataReference getReference(List<MetadataReference> refs , String id){
        for (MetadataReference ref : refs) {
            if (id.equals(ref.getDependentMetadata().getId())){
                return ref;
            }
        }
        return null;
    }
}
